package com.qst.order.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qst.order.domain.DTO.*;
import com.qst.order.domain.Order;
import com.qst.order.domain.OrderItem;
import com.qst.order.mapper.OrderItemMapper;
import com.qst.order.mapper.OrderMapper;
import com.qst.order.service.OrderItemService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class OrderItemServiceImpl extends ServiceImpl<OrderItemMapper, OrderItem> implements OrderItemService {

    private final OrderItemMapper orderItemMapper;
    private final OrderMapper orderMapper;

    @Override
    /**
     * 获取指定日期范围内的订单商品明细
     * @param start 开始时间
     * @param end 结束时间
     * @param merchantId 商家ID（当前登录商家）
     * @return 订单商品明细DTO列表
     */
    public List<OrderItemDTO> getOrderItemList(LocalDate  start, LocalDate  end, Integer merchantId) {
        return orderItemMapper.selectOrderItemDTOByDateRange(start, end, merchantId);
    }


    /**
     * 获取概览统计数据
     */
    @Override
    public OverviewDTO getOverview(LocalDate start, LocalDate end, Integer merchantId) {
        // 1. 当前周期数据
        BigDecimal currentSales = getTotalSales(start, end, merchantId);
        Integer currentOrders = getTotalOrders(start, end, merchantId);
        Integer currentProductsSold = getTotalProductsSold(start, end, merchantId);

        // 2. 上一周期数据（用于计算趋势）
        // 关键修改：使用 ChronoUnit.DAYS 计算 LocalDate 之间的天数
        long days = ChronoUnit.DAYS.between(start, end);
        LocalDate lastPeriodStart = start.minusDays(days);
        LocalDate lastPeriodEnd = end.minusDays(days);

        BigDecimal lastSales = getTotalSales(lastPeriodStart, lastPeriodEnd, merchantId);
        Integer lastOrders = getTotalOrders(lastPeriodStart, lastPeriodEnd, merchantId);
        Integer lastProductsSold = getTotalProductsSold(lastPeriodStart, lastPeriodEnd, merchantId);

        // 3. 计算平均订单金额
        BigDecimal avgOrderAmount = currentOrders > 0
                ? currentSales.divide(BigDecimal.valueOf(currentOrders), 2, BigDecimal.ROUND_HALF_UP)
                : BigDecimal.ZERO;

        // 4. 计算趋势百分比
        double salesTrend = calculateTrend(currentSales, lastSales);
        double ordersTrend = calculateTrend(currentOrders, lastOrders);
        double productsTrend = calculateTrend(currentProductsSold, lastProductsSold);
        double avgTrend = calculateAvgTrend(currentSales, currentOrders, lastSales, lastOrders);

        // 封装结果
        OverviewDTO dto = new OverviewDTO();
        dto.setTotalSales(currentSales);
        dto.setTotalOrders(currentOrders);
        dto.setAvgOrderAmount(avgOrderAmount);
        dto.setTotalProductsSold(currentProductsSold);
        dto.setSalesTrendPercent(salesTrend);
        dto.setOrdersTrendPercent(ordersTrend);
        dto.setAvgTrendPercent(avgTrend);
        dto.setProductsTrendPercent(productsTrend);

        return dto;
    }
    // 计算总销售额
    private BigDecimal getTotalSales(LocalDate  start, LocalDate  end, Integer merchantId) {
        return orderItemMapper.sumTotalPriceByDateAndMerchant(start, end, merchantId);
    }

    // 计算总订单数
    private Integer getTotalOrders(LocalDate  start, LocalDate  end, Integer merchantId) {
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.between("create_time", start, end)
                .eq("is_deleted", 0)
                .inSql("order_id", "SELECT DISTINCT order_id FROM t_order_item WHERE merchant_id = " + merchantId);
        return Math.toIntExact(orderMapper.selectCount(wrapper));
    }

    // 计算商品销售总量
    private Integer getTotalProductsSold(LocalDate  start, LocalDate  end, Integer merchantId) {
        return orderItemMapper.sumQuantityByDateAndMerchant(start, end, merchantId);
    }

    // 计算趋势百分比（当前/上期 - 1）
    private double calculateTrend(Number current, Number last) {
        if (last.doubleValue() == 0) {
            return current.doubleValue() > 0 ? 100 : 0; // 上期为0时，本期有值则视为100%增长
        }
        return ((current.doubleValue() / last.doubleValue()) - 1) * 100;
    }

    // 计算平均订单金额趋势
    private double calculateAvgTrend(BigDecimal currSales, int currOrders,
                                     BigDecimal lastSales, int lastOrders) {
        if (currOrders == 0 || lastOrders == 0) return 0;
        BigDecimal currAvg = currSales.divide(BigDecimal.valueOf(currOrders), 2, BigDecimal.ROUND_HALF_UP);
        BigDecimal lastAvg = lastSales.divide(BigDecimal.valueOf(lastOrders), 2, BigDecimal.ROUND_HALF_UP);
        return ((currAvg.doubleValue() / lastAvg.doubleValue()) - 1) * 100;
    }
    /**
     * 获取趋势数据（补全缺失的时间点）
     */
    public TrendDTO getTrend(LocalDate start, LocalDate end, Integer merchantId) {
        // 1. 确定分组粒度（天/周/月），并修正周粒度格式
        long days = ChronoUnit.DAYS.between(start, end);
        String groupFormat; // SQL的DATE_FORMAT格式
        String javaFormat;  // Java的DateTimeFormatter格式（用于生成时间标签）
        if (days <= 31) {
            // 31天内按天分组
            groupFormat = "%Y-%m-%d";
            javaFormat = "yyyy-MM-dd";
        } else if (days <= 90) {
            // 3个月内按周分组（ISO周数：1-53，每年第1周至少包含4天）
            groupFormat = "%Y-%u"; // SQL中%u表示周数（1-53）
            javaFormat = "yyyy-ww"; // Java中ww表示周数（1-53）
        } else {
            // 超过3个月按月分组
            groupFormat = "%Y-%m";
            javaFormat = "yyyy-MM";
        }

        // 2. 查询数据库中的实际数据（可能有缺失）
        List<TrendItem> dbItems = orderItemMapper.selectTrendData(
                start, end, merchantId, groupFormat);

        // 3. 生成完整的时间标签列表（覆盖start到end的所有时间点）
        List<String> fullLabels = generateFullTimeLabels(start, end, javaFormat, groupFormat);

        // 4. 将数据库数据转为Map（key：时间标签，value：TrendItem），方便匹配
        Map<String, TrendItem> dbItemMap = dbItems.stream()
                .collect(Collectors.toMap(TrendItem::getDateLabel, item -> item));

        // 5. 补全数据：遍历完整标签，缺失的用0填充
        TrendDTO result = new TrendDTO();
        result.setLabels(fullLabels); // 设置完整的时间标签

        for (String label : fullLabels) {
            TrendItem item = dbItemMap.getOrDefault(label, new TrendItem());
            // 确保数值不为null（用0填充）
            result.getSalesData().add(Optional.ofNullable(item.getSales()).orElse(BigDecimal.valueOf(0.0)));
            result.getOrdersData().add(Optional.ofNullable(item.getOrders()).orElse(0));
        }

        return result;
    }

    /**
     * 生成完整的时间标签列表（核心工具方法）
     * @param start 开始日期
     * @param end 结束日期
     * @param javaFormat Java格式化字符串（如yyyy-MM-dd）
     * @param groupFormat SQL分组格式（用于判断粒度）
     */
    private List<String> generateFullTimeLabels(LocalDate start, LocalDate end,
                                                String javaFormat, String groupFormat) {
        List<String> labels = new ArrayList<>();
        LocalDate current = start;
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(javaFormat);

        while (!current.isAfter(end)) { // 循环生成所有时间点
            labels.add(current.format(formatter));
            // 根据分组粒度递增时间
            if (groupFormat.contains("%d")) { // 天粒度：每次+1天
                current = current.plusDays(1);
            } else if (groupFormat.contains("%u")) { // 周粒度：每次+1周
                current = current.plusWeeks(1);
            } else { // 月粒度：每次+1月
                current = current.plusMonths(1);
            }
        }

        return labels;
    }

    @Override
    public StatusDistributionDTO getOrderStatusDistribution(LocalDate start, LocalDate  end, Integer merchantId) {
        // 1. 查询状态分布原始数据（英文状态）
        List<StatusCount> statusCounts = orderMapper.selectStatusCount(start, end, merchantId);

        // 2. 转换状态为中文并封装结果
        StatusDistributionDTO dto = new StatusDistributionDTO();
        statusCounts.forEach(count -> {
            String chineseStatus = convertStatusToChinese(count.getStatus());
            dto.getStatusLabels().add(chineseStatus);
            dto.getStatusData().add(count.getCount());
        });
        return dto;
    }

    // 状态转换：英文 -> 中文
    private String convertStatusToChinese(String status) {
        Map<String, String> statusMap = new HashMap<>();
        statusMap.put("PENDING_PAY", "待支付");
        statusMap.put("PAID", "已支付");
        statusMap.put("SHIPPED", "已发货");
        statusMap.put("COMPLETED", "已完成");
        statusMap.put("CANCELED", "已取消");
        statusMap.put("REFUNDED", "已退款");
        return statusMap.getOrDefault(status, status);
    }

    @Override
    public List<TopProductDTO> getTopProducts(LocalDate  start, LocalDate  end,
                                              Integer merchantId, Integer topN) {
        // 1. 查询热销商品数据
        List<TopProductDTO> topProducts = orderItemMapper.selectTopProducts(
                start, end, merchantId, topN);

        // 2. 计算总销售额（用于计算占比）
        BigDecimal totalSales = getTotalSales(start, end, merchantId);

        // 3. 计算每个商品的销售额占比
        topProducts.forEach(product -> {
            if (totalSales.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal percentage = product.getTotalRevenue()
                        .divide(totalSales, 4, BigDecimal.ROUND_HALF_UP);
                product.setPercentage(percentage.doubleValue());
            } else {
                product.setPercentage(0.0);
            }
        });

        return topProducts;
    }

}
